#include<iostream>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<cstring>
#include"err.hpp"

using namespace std;

const uint16_t default_port = 8080;

typedef string(*func_t)(string);

class ns_server
{
public:
  ns_server(func_t func,uint16_t port = default_port)
    :_port(port)
    ,_func(func)
  {
    cout << "port : " << _port << endl;
  }

  void Start()
  {
    _socket = socket(AF_INET,SOCK_DGRAM,0);
    if(_socket == -1)
    {
      cerr <<"create socket error" << endl;
      exit(SOCKET_ERR); 
    }
    cout << "create socket success" << endl;

    struct sockaddr_in local;
    memset(&local,0,sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(_port);
    local.sin_addr.s_addr = INADDR_ANY;//让server启动的时候，挂接主机上的任意IP，sin_addr是结构体

  cout << "sin_family : " << AF_INET << " sin_port : " << local.sin_port << " s._addr " << local.sin_addr.s_addr << endl;
    if(bind(_socket,(struct sockaddr*)&local,sizeof(local)) < 0)
    {
      cerr << "bind socket error" << endl;
      exit(BIND_ERR);
    }
    cout << "bind socket success" << endl;
  }
  
  void rev()
  {
    char buffer[1024];
    while(true)
    {
      struct sockaddr_in local;
      socklen_t len = sizeof(local);
      ssize_t n = recvfrom(_socket,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&local,&len);
      if(n > 0)
        buffer[n] = '\0';
      else
        continue;
      cout << "client send message : " << buffer << endl;
      
       std::string clientip = inet_ntoa(local.sin_addr);
       uint16_t clientport = ntohs(local.sin_port);
       std::cout << clientip << "-" << clientport << "# " << buffer << std::endl;
       
       std::string str = _func(buffer);

       std::string name = clientip;
       std::string message = name + ">> " + str;


      sendto(_socket,str.c_str(),str.size(),0,(struct sockaddr*)&local,len);
    }
  }
    
  ~ns_server()
  {}
private:
  int _socket;
  uint16_t _port;
  func_t _func;
};
